import java.util.*;

public class BlockingQueue {
 private int[] items = new int[1000];
 private volatile int size = 0;
 private volatile int head = 0;
 private volatile int tail = 0;
 public void put(int value) throws InterruptedException {
 synchronized (this) {
 // 此处最好使⽤ while.
 // 否则 notifyAll 的时候, 该线程从 wait 中被唤醒,
 // 但是紧接着并未抢占到锁. 当锁被抢占的时候, 可能⼜已经队列满了
 // 就只能继续等待
  while (size == items.length) {
   wait();
  }
  items[tail] = value;
  tail = (tail + 1) % items.length;
  size++;
  notifyAll();
 }
 }
 public int take() throws InterruptedException {
  int ret = 0;
  synchronized (this) {
   while (size == 0) {
    wait();
   }
   ret = items[head];
   head = (head + 1) % items.length;
   size--;
   notifyAll();
  }
  return ret;
 }
 public synchronized int size() {
  return size;
 }
 public static void main(String[] args) throws InterruptedException {
  BlockingQueue blockingQueue = new BlockingQueue();
  Thread customer = new Thread(() -> {
   while (true) {
    try {
     int value = blockingQueue.take();
     System.out.println(value);
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
   }
  }, "消费者");
  customer.start();
  Thread producer = new Thread(() -> {
   Random random = new Random();
   while (true) {
    try {
     blockingQueue.put(random.nextInt(10000));
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
   }
  }, "⽣产者");
   producer.start();

 customer.join();
 producer.join();
 }
 }